﻿// Copyright (c) 2011 OpenNETCF Consulting, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
// associated documentation files (the "Software"), to deal in the Software without restriction, including 
// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to 
// the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial 
// portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace OpenNETCF.SplashGenerator
{
    public partial class MainForm : Form
    {
        private string m_sourceFile;

        public MainForm()
        {
            InitializeComponent();

            sourceFile.TextChanged += new EventHandler(sourceFile_TextChanged);
        }

        void sourceFile_TextChanged(object sender, EventArgs e)
        {
            if (File.Exists(sourceFile.Text))
            {
                generate.Enabled = true;
                m_sourceFile = sourceFile.Text;
                try
                {
                    this.picture.ImageLocation = sourceFile.Text;
                }
                catch
                {
                    return;
                }
            }
            else
            {
                generate.Enabled = true;
                m_sourceFile = null;
                    this.picture.ImageLocation = null;
            }
        }

        private void browse_Click(object sender, EventArgs e)
        {
            var ofd = new OpenFileDialog()
            {
                Filter = "Image Files (*.bmp, *.jpg, *.png, *.gif)|*.bmp;*.jpg;*.png;*.gif",
                CheckFileExists = true,
                Multiselect = false,
                Title = "Select Source Image"
            };

            if (ofd.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
            {
                generate.Enabled = false;

                var filename = ofd.FileName;

                if (string.IsNullOrEmpty(filename)) return;
                if (!File.Exists(filename)) return;

                m_sourceFile = ofd.FileName;
                sourceFile.Text = m_sourceFile;
            }
        }

        private void convert_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            generate.Enabled = false;
            Application.DoEvents();

            try
            {
                var converted = ConvertImage();

                if (converted != null)
                {
                    BinCompress(converted);
                    MessageBox.Show("Conversion complete", "Success");
                }
            }
            finally
            {
                Cursor.Current = Cursors.Default;
                generate.Enabled = true;
            }
        }

        private void BinCompress(string sourceFile)
        {
            var bincomp = Path.Combine(Application.StartupPath, "bincompress.exe");

            if (!File.Exists(bincomp))
            {
                using (var stream = File.Create(bincomp))
                using (var writer = new BinaryWriter(stream))
                {
                    writer.Write(Properties.Resources.bincompress);
                }
            }

            var cmdline = string.Format("/c \"{0}\" \"{1}\"",
                sourceFile,
                Path.Combine(Path.GetDirectoryName(sourceFile), "splash.bmx"));

            var p = new Process();
            p.StartInfo =
                new ProcessStartInfo(bincomp, cmdline)
                {
                    CreateNoWindow = true,
                    RedirectStandardOutput = true,
                    UseShellExecute = false
                };

            p.Start();
            var output = p.StandardOutput.ReadToEnd().Replace('\b', ' ');
            p.WaitForExit();
            result.Text = output;

            File.Delete(sourceFile);
        }

        private string ConvertImage()
        {
            var destPath = Path.GetDirectoryName(m_sourceFile);
            var destFile = Path.GetFileNameWithoutExtension(m_sourceFile);
            destFile = string.Format("{0}16.bmp", destFile);
            destFile = Path.Combine(destPath, destFile);

            try
            {
                Bitmap src = null;
                try
                {
                    src = new Bitmap(m_sourceFile);

                    // check size - we must be below 64k
                    var size = src.Width * src.Height * ImageConverter.GetPixelInfoSize(src.PixelFormat);
                    if (size > 0x10000)
                    {
                        var resize = MessageBox.Show(
                            "Resulting image will be > 64k, which is unlikely to work on the target.  Would you like to attempt to resize it?",
                            "Image is too large",
                            MessageBoxButtons.YesNoCancel,
                            MessageBoxIcon.Question);

                        switch (resize)
                        {
                            case System.Windows.Forms.DialogResult.Yes:
                                size = src.Width * src.Height;
                                // since the stride is always divisible by 4, we need a "fudge factor", so we'll shoot for < 62k
                                var scale = Math.Sqrt(size / (double)62000);
                                var temp = new Bitmap((int)(src.Width / scale), (int)(src.Height / scale), src.PixelFormat);
                                Debug.WriteLine(string.Format("new {0}x{1} = {2}", temp.Width, temp.Height, temp.Width * temp.Height));
                                using (Graphics g = Graphics.FromImage(temp))
                                {
                                    g.DrawImage(src, 0, 0, temp.Width, temp.Height);
                                }
                                src.Dispose();
                                src = temp;
                                break;
                            case System.Windows.Forms.DialogResult.No:
                                // do nothing, go ahead and generate splash.bmx
                                break;
                            case System.Windows.Forms.DialogResult.Cancel:
                                // don't generate bmx file
                                return null;
                        }
                    }


                    using (var dest = ImageConverter.ConvertTo8bppFormat(src))
                    {
                        dest.Save(destFile, ImageFormat.Bmp);
                    }
                }
                finally
                {
                    src.Dispose();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Unable to convert file:\r\n" + ex.Message, "Error");
                return null;
            }

            return destFile;
        }
    }
}
